package main

import (
	"log"
	"github.com/boltdb/bolt"
	"fmt"
	"time"
	"os"
	"encoding/json"
)

func main() {
	// Open the my.db data file in your current directory.
	// It will be created if it doesn't exist.
	db, err := bolt.Open("my.db", 0600, nil)
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	db.Update(func(tx *bolt.Tx) error {
		b, err := tx.CreateBucket([]byte("MyBucket"))
		if err != nil {
			return fmt.Errorf("create bucket: %s", err)
		}
		fmt.Println(b)
		return nil
	})

	db.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte("MyBucket"))
		err := b.Put([]byte("answer"), []byte("41"))
		return err
	})

	db.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte("MyBucket"))
		v := b.Get([]byte("answer"))
		fmt.Printf("[get] The answer is: %s\n", v)
		return nil
	})

	//迭代
	//During iteration, if the key is non-nil but the value is nil, that means 
	//the key refers to a bucket rather than a value. Use Bucket.Bucket() to access the sub-bucket.
	db.View(func(tx *bolt.Tx) error {
		// Assume bucket exists and has keys
		b := tx.Bucket([]byte("MyBucket"))

		c := b.Cursor()

		for k, v := c.First(); k != nil; k, v = c.Next() {
			fmt.Printf("[cursor] key=%s, value=%s\n", k, v)
		}

		return nil
	})

	db.View(func(tx *bolt.Tx) error {
		// Assume bucket exists and has keys
		b := tx.Bucket([]byte("MyBucket"))

		b.ForEach(func(k, v []byte) error {
			fmt.Printf("[foreach] key=%s, value=%s\n", k, v)
			return nil
		})
		return nil
	})

	/*
		The database keeps a running count of many of the internal operations it performs so you can better
		understand what's going on. By grabbing a snapshot of these stats at two points in time we can see
		what operations were performed in that time range.
		It's also useful to pipe these stats to a service such as statsd for monitoring or to provide an 
		HTTP endpoint that will perform a fixed-length sample.

		For example, we could start a goroutine to log stats every 10 seconds:
	*/
	go func() {
		// Grab the initial stats.
		prev := db.Stats()

		for {
			// Wait for 10s.
			time.Sleep(10 * time.Second)

			// Grab the current stats and diff them.
			stats := db.Stats()
			diff := stats.Sub(&prev)

			// Encode stats to JSON and print to STDERR.
			json.NewEncoder(os.Stderr).Encode(diff)

			// Save stats for the next loop.
			prev = stats
		}
	}()
}